﻿Imports System.Web
Imports System.Text.RegularExpressions
Imports System.Reflection
Imports System.Text

Namespace DotNetNuke.Modules.ActiveForums
    Partial Class Utilities
        Public Class JSON
            Public Shared Function Pair(ByVal name As String, ByVal value As String) As String
                Return Pair(name, value, False)
            End Function
            Public Shared Function Pair(ByVal name As String, ByVal value As String, ByVal isObject As Boolean) As String
                If String.IsNullOrEmpty(value) Then
                    value = Chr(34) & Chr(34)
                ElseIf Not IsNumeric(value) And Not (value.ToLower = "true" Or value.ToLower = "false") And isObject = False Then
                    value = Chr(34) & JSON.EscapeJsonString(value) & Chr(34)
                ElseIf value.Trim.ToLowerInvariant = "true" Or value.Trim.ToLowerInvariant = "false" Then
                    value = value.Trim.ToLower
                End If
                Return Chr(34) & name & Chr(34) & ":" & value
            End Function
            Public Shared Function ConvertToJSONAssociativeArray(ByVal dict As Dictionary(Of String, String)) As String
                Dim elements As List(Of String) = New List(Of String)()
                For Each Pair As KeyValuePair(Of String, String) In dict
                    If Not String.IsNullOrEmpty(Pair.Value) Then
                        elements.Add(String.Format("""{0}"":{2}{1}{2}", EscapeJsonString(Pair.Key), EscapeJsonString(Pair.Value), If(IsJSONArray(Pair.Value) OrElse IsBoolean(Pair.Value), String.Empty, """")))
                    End If
                Next
                Return "{" & String.Join(",", elements.ToArray()) & "}"
            End Function
            Public Shared Function IsJSONArray(ByVal test As String) As Boolean
                Return test.StartsWith("{") AndAlso Not test.StartsWith("{*") OrElse test.StartsWith("[")
            End Function
            Public Shared Function IsBoolean(ByVal test As String) As Boolean
                Return test.Equals("false") OrElse test.Equals("true")
            End Function
            Public Shared Function ConvertToJSONArray(ByVal list As List(Of String)) As String
                Dim builder As New StringBuilder()
                builder.Append("[")
                For Each item As String In list
                    builder.Append(String.Format("{0}{1}{0},", If(IsJSONArray(item) OrElse IsBoolean(item), String.Empty, """"), EscapeJsonString(item)))
                Next
                builder.Replace(",", "]", builder.Length - 1, 1)
                Return builder.ToString()
            End Function
            Public Shared Function ConvertFromJSONToObject(ByVal array As String, ByVal InfoObject As Object) As Object
                Dim dict As Dictionary(Of String, String) = ConvertFromJSONAssoicativeArray(array)
                If dict.Count > 0 Then
                    Dim myType As Type = InfoObject.GetType()
                    Dim myProperties() As System.Reflection.PropertyInfo = myType.GetProperties((System.Reflection.BindingFlags.Public Or BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance))
                    Dim sKey As String = String.Empty
                    Dim sValue As String = String.Empty
                    For Each pItem As PropertyInfo In myProperties
                        sValue = String.Empty
                        sKey = pItem.Name.ToLower
                        If dict.ContainsKey(sKey) Then
                            sValue = dict.Item(sKey)
                        End If
                        If Not String.IsNullOrEmpty(sValue) Then
                            Dim obj As Object = Nothing
                            Select Case pItem.PropertyType.ToString
                                Case "System.Int16"
                                    obj = CType(sValue, Integer)
                                Case "System.Int32"
                                    obj = CType(sValue, Integer)
                                Case "System.Int64"
                                    obj = CType(sValue, Long)
                                Case "System.Single"
                                    obj = CType(sValue, Single)
                                Case "System.Double"
                                    obj = CType(sValue, Double)
                                Case "System.Decimal"
                                    obj = CType(sValue, Decimal)
                                Case "System.DateTime"
                                    obj = CType(sValue, DateTime)
                                Case "System.String", "System.Char"
                                    obj = CType(sValue, String)
                                Case "System.Boolean"
                                    obj = CType(sValue, Boolean)
                                Case "System.Guid"
                                    obj = New Guid(sValue)

                            End Select
                            If Not obj Is Nothing Then
                                InfoObject.GetType().GetProperty(pItem.Name).SetValue(InfoObject, obj, BindingFlags.Public Or BindingFlags.NonPublic, Nothing, Nothing, Nothing)
                            End If

                        End If
                    Next
                End If
                Return InfoObject
            End Function
            Public Shared Function ConvertFromJSONArray(ByVal array As String) As List(Of String)
                If Not String.IsNullOrEmpty(array) Then
                    array = array.Replace("[", "").Replace("]", "").Replace("""", "")
                    Return New List(Of String)(array.Split(","c))
                Else
                    Return New List(Of String)()
                End If
            End Function
            Public Shared Function ConvertFromJSONAssoicativeArray(ByVal array As String) As Dictionary(Of String, String)
                Dim dict As Dictionary(Of String, String) = New Dictionary(Of String, String)()
                If Not String.IsNullOrEmpty(array) Then
                    If array.StartsWith("{") Then
                        array = array.Substring(1)
                    End If
                    If array.EndsWith("}") Then
                        array = array.Substring(0, array.Length - 1)
                    End If
                    array = array.Replace(""":", "|").Replace("""", "").Replace("\/", "/").Replace(", ", "#^")
                    Dim pairs As List(Of String) = New List(Of String)(array.Split(","c))
                    For Each pair As String In pairs
                        If Not String.IsNullOrEmpty(pair) Then
                            Dim pairArray As String() = pair.Split("|"c)
                            Dim val As String = String.Empty
                            If pairArray.Length = 2 Then
                                val = pairArray(1)
                            End If
                            val = val.Replace("#^", ", ")
                            dict.Add(pairArray(0), HttpUtility.UrlDecode(val))
                        End If
                    Next
                    Return dict
                Else
                    Return New Dictionary(Of String, String)()
                End If
            End Function
            Public Shared Function ConvertFromJSONAssoicativeArrayToHashTable(ByVal array As String) As Hashtable
                Dim ht As New Hashtable
                If Not String.IsNullOrEmpty(array) Then
                    If array.StartsWith("{") Then
                        array = array.Substring(1)
                    End If
                    If array.EndsWith("}") Then
                        array = array.Substring(0, array.Length - 1)
                    End If
                    array = array.Replace(""":", "|").Replace("""", "").Replace("\/", "/").Replace(", ", "#^")
                    Dim pairs As List(Of String) = New List(Of String)(array.Split(","c))
                    For Each pair As String In pairs
                        If Not String.IsNullOrEmpty(pair) Then
                            Dim pairArray As String() = pair.Split("|"c)
                            Dim val As String = String.Empty
                            If pairArray.Length = 2 Then
                                val = pairArray(1)
                            End If
                            val = val.Replace("#^", ", ")
                            ht.Add(pairArray(0), val)
                        End If
                    Next
                    Return ht
                Else
                    Return ht
                End If
            End Function
            ''' <summary>
            ''' Escape backslashes and double quotes
            ''' </summary>
            ''' <param name="originalString">string</param>
            ''' <returns>string</returns>
            Friend Shared Function EscapeJsonString(ByVal originalString As String) As String
                Dim reg As New Regex("\s+", RegexOptions.Multiline)
                originalString = reg.Replace(originalString, " ")
                Return If(IsJSONArray(originalString), originalString, originalString.Replace("\/", "/").Replace("/", "\/").Replace("\""", """").Replace("""", "\""").Replace(vbNewLine, String.Empty))
            End Function
        End Class

    End Class
End Namespace

